package com.gcsj.gcsjspringboot.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gcsj.gcsjspringboot.common.utils.Constant;
import com.gcsj.gcsjspringboot.common.utils.DateUtils;
import com.gcsj.gcsjspringboot.common.utils.PageUtils;
import com.gcsj.gcsjspringboot.common.utils.Query;
import com.gcsj.gcsjspringboot.constant.WorkStatusEnum;
import com.gcsj.gcsjspringboot.dao.SalaryRecordDao;
import com.gcsj.gcsjspringboot.entity.*;
import com.gcsj.gcsjspringboot.service.*;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;


@Service("salaryRecordService")
public class SalaryRecordServiceImpl extends ServiceImpl<SalaryRecordDao, SalaryRecordEntity> implements SalaryRecordService {
    @Autowired
    SysUserService userService;
    @Autowired
    SysDeptService deptService;

    @Autowired
    WorkRecordService workRecordService;
    @Autowired
    IncentiveService incentiveService;
    @Autowired
    SysVarService sysVarService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Integer userId = (Integer)params.get("userId");
        String rdDate = (String) params.get("rdDate");
        IPage<SalaryRecordEntity> page = this.page(
                new Query<SalaryRecordEntity>().getPage(params),
                new QueryWrapper<SalaryRecordEntity>().eq(userId!=null&&userId!=-1, "user_id", userId).eq(StringUtils.isNotBlank(rdDate), "salary_month", rdDate)
        );
        return new PageUtils(page);
    }


    @Override
    public void deleteBatch(Long[] ids) {
        this.removeByIds(Arrays.asList(ids));

    }

    @Override
    public void update(SalaryRecordEntity record) {
        this.updateById(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int genSalaryT(String date) {
        if("undefined".equals(date)){
            date = DateUtils.format(new Date()).substring(0, 7);
        }
            int count = count(new QueryWrapper<SalaryRecordEntity>()
                .eq("salary_month", date));
        if(count==0){
            List<SalaryRecordEntity> data = genSalary(date);
            this.saveBatch(data);
            return 0;
        }
        return -1;
    }


    public List<SalaryRecordEntity> genSalary(String date){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<SalaryRecordEntity> datalist = new ArrayList<>();
        List<SysUserEntity> users = userService.list();

        for (SysUserEntity user : users) {
            int userId = user.getUserId().intValue();
            Float mustSalary = user.getMustSalary();
            Float jxScore = user.getJxScore();
            String entryDate = user.getEntryDate();

            SalaryRecordEntity salaryRecord = new SalaryRecordEntity();

            // 薪资月份
            salaryRecord.setSalaryMonth(date);

            // 基本工资
            salaryRecord.setMustSalary(mustSalary);

            // 全勤工资 = 基本工资 * 实际出勤天数 / 应出勤天数  * 0.03
            float realitySalaryNum = getRealitySalary(userId);
            salaryRecord.setRealitySalary(mustSalary * realitySalaryNum * 0.03f);

            // 总扣款
            float allFine = getAllFine(userId, 2);
            salaryRecord.setFineAmount(allFine);

            // 绩效奖金 = 基本工资 * 基数 * 绩效得分
            SysVar jx = sysVarService.getOne(new QueryWrapper<SysVar>()
                    .eq("sys_name", "绩效得分基数"));
            float jxjj = mustSalary * jxScore * Float.parseFloat(jx.getSysVal());
            salaryRecord.setMedicalAmount(jxjj);

            // 五险一金
            SysVar wx = sysVarService.getOne(new QueryWrapper<SysVar>()
                    .eq("sys_name", "社保基数"));
            Integer baseSb = Integer.parseInt(wx.getSysVal());
            // 养老保险
            double yl = baseSb * 0.08;
            // 医疗保险
            double yliao = baseSb * 0.02;
            // 失业保险
            double sy = baseSb * 0.05;
            // 住房公积金
            double zf = baseSb * 0.12;
            double wxyj = yl + yliao + sy + zf;
            salaryRecord.setInjuredAmount((float)wxyj * (-1));

            // 工龄工资
            SysVar gl = sysVarService.getOne(new QueryWrapper<SysVar>()
                    .eq("sys_name", "工龄工资基数"));
            Integer baseGl = Integer.parseInt(gl.getSysVal());
            int entryYear = Integer.parseInt(entryDate.split("-")[0]);
            int nowYear = Calendar.getInstance().get(Calendar.YEAR);
            int entryYears = nowYear - entryYear;
            salaryRecord.setWorkAmount((entryYears + 1) * baseGl + 0f);

            // 奖励
            float jlVal = getAllFine(userId, 1);
            salaryRecord.setRewardAmount(jlVal);

            // 个税 = 应纳税所得额×税率-速算扣除数。应纳税所得额 = 税前收入 - 五险一金 - 起征点
            // 个税暂时未考虑有子女时的1000和房贷1000等等
            SysVar qzd = sysVarService.getOne(new QueryWrapper<SysVar>()
                    .eq("sys_name", "纳税起征点"));
            Integer qzdVal = Integer.parseInt(qzd.getSysVal());
            // 应纳税所得额
            Float sVal = salaryRecord.getSVal(qzdVal);
            if(sVal == 0){
                salaryRecord.setPensionAmount(0f);
            } else {
                salaryRecord.setPensionAmount(getGs(sVal));
            }
            salaryRecord.setCreateTime(DateUtils.format(new Date()));
            salaryRecord.setUserId(userId);
            datalist.add(salaryRecord);
        }
        return datalist;
    }
        private float getGs(Float taxableIncome) {
            double tax = 0.0;
            if (taxableIncome <= 0) {
                tax = 0.0;
            } else if (taxableIncome <= 36000) {
                tax = taxableIncome * 0.03;
            } else if (taxableIncome <= 144000) {
                tax = taxableIncome * 0.1 - 2520;
            } else if (taxableIncome <= 300000) {
                tax = taxableIncome * 0.2 - 16920;
            } else if (taxableIncome <= 420000) {
                tax = taxableIncome * 0.25 - 31920;
            } else if (taxableIncome <= 660000) {
                tax = taxableIncome * 0.3 - 52920;
            } else if (taxableIncome <= 960000) {
                tax = taxableIncome * 0.35 - 85920;
            } else {
                tax = taxableIncome * 0.45 - 181920;
            }
            return (float) tax * -1;
        }
        private float getRealitySalary(Integer userId){
        List<WorkRecordEntity> user_works = workRecordService.list(new QueryWrapper<WorkRecordEntity>()
                .eq("user_id", userId));
        int num = 0;
        for (WorkRecordEntity user_work : user_works) {
            if (WorkStatusEnum.NORMAL.getCode() == user_work.getStatus()) {
                num++;
            }
        }
        if(user_works.size() == 0){
            return 0;
        }
        return num/user_works.size();
    }
    private float getAllFine(Integer userId, Integer type){
        double total = 0;
        List<Incentive> list = incentiveService.list(new QueryWrapper<Incentive>()
                .eq("type", type)
                .eq("user_id", userId));
        for (Incentive incentive : list) {
            Double rpMny = incentive.getRpMny();
            total+=rpMny;
        }
        float rst = (float) total;
        return type == 1 ? rst : rst * (-1);
    }


}
